package com.xuzz.study.spring.factorybean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class PersonService {

    /**
     * 可以用autowired来注入FactoryBean产生的对象。
     * 因为在beanfactory.getBean中，会有FactoryBean的特殊处理：实现了FactoryBean接口的实现类，在容器中默认获取得到的是工厂bean调用getObject方法创建的对象。
     *
     *   protected Object getObjectForBeanInstance(
     *             Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
     *
     *         //如果是对FactoryBean的解引用，但bean对象不是FactoryBean，抛出异常
     *         if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
     *             throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
     *         }
     *
     *         //如果Bean实例不是FactoryBean，或者指定名称是FactoryBean的解引用，也就是普通的bean调用，则直接返回当前的Bean实例
     *         if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
     *             return beanInstance;
     *         }
     *
     *         //处理对FactoryBean的调用
     *         Object object = null;
     *         if (mbd == null) {
     *             //从Bean工厂缓存中获取给定名称的实例对象
     *             object = getCachedObjectForFactoryBean(beanName);
     *         }
     *         if (object == null) {
     *             // Return bean instance from factory.
     *             FactoryBean factory = (FactoryBean) beanInstance;
     *             //如果从Bean工厂生产的Bean是单态模式的，则缓存
     *             if (mbd == null && containsBeanDefinition(beanName)) {
     *                 mbd = getMergedLocalBeanDefinition(beanName);
     *             }
     *             boolean synthetic = (mbd != null && mbd.isSynthetic());
     *             //调用FactoryBeanRegistrySupport类的getObjectFromFactoryBean方法，实现FactoryBean生产Bean对象实例的过程
     *             object = getObjectFromFactoryBean(factory, beanName, !synthetic);
     *         }
     *         return object;
     *     }
     *
     *
     *    dubbo的reference，也可以autowired，就是因为ReferenceBean实现了FactoryBean接口。所以在Spring Container可以Autowired。
     *
     *    https://blog.csdn.net/dbeautifullife/article/details/73238362
     *    https://blog.csdn.net/liujun03/article/details/81485843
     *
     *    而要获取FactoryBean自己，则需要使用"&xxFactoryBean"的方式获取
     */
    @Autowired
    Person person;

    public void say()
    {
        person.setName("x");
        person.setAge(100);
        System.out.println(person.toString());
    }
}
